#include <stdio.h>
#include "glann.h"

#include <unistd.h>

void print_weight(struct glann_weight_s *w)
{
    int i,j;
    printf("\r\n[weight] forward nueres: %d current nueres: %d\r\n\r\n", w->forward_layer_num,  w->current_layer_num);
    for(i = 0; i < w->current_layer_num; i++){
        printf("neure[%d]\r\n",i);
        for(j = 0; j <  w->forward_layer_num; j++){
            printf("%10.6f",glann_weight_get(w,i,j));
        }
        printf("\r\n");
    }

}

struct number_sample_s{
    float input[7];
    float output;
};

void print_layer(struct glann_layer_s *layer)
{
    int i;
    printf("input:");
    for(i = 0; i < layer->nuere_num; i++){
        printf(" %7.3f ",layer->neures[i].input);
    }
    printf("\r\noutput:");
    for(i = 0; i < layer->nuere_num; i++){
        printf(" %7.3f ",layer->neures[i].output);
    }
    printf("\r\n");
}


void fun(float x1, float x2, float x3, float *y1, float *y2)
{
    *y1 = 2 * x1 * x1 + x2 + x3;
    *y2 = x2 - 5 * x2 * x3;
}

int main(int argc, char *argv[])
{
    struct glann_network_s numrec;
    unsigned short numrec_desc[9] = {10,6,2,2,30,20,10,6,2};

    char *model_path = "./function_recognize_a.model";

    glann_network_create(&numrec,numrec_desc,3);

    printf("\r\n**********************     start    ***********************\r\n");

    int i,j,k;

    float ibuf[10];
    float obuf[10];
    float pbuf[10];
    struct glann_iodata_s tdat;

    tdat.input        = ibuf;
    tdat.output       = obuf;
    tdat.probability  = pbuf;

    tdat.input_size  = 10;
    tdat.output_size = 2;

    for(j = 0; j < 5000000; j++){

        int index = j % 200;

        float x1 =  0.004f * (float)index;
        float x2 = -0.004f * (float)index;
        float x3 =  0.005f * (float)index;

        float res1,res2;

        fun(x1,x2,x3,&res1,&res2);

        tdat.input[0] = x1;
        tdat.input[1] = x2;
        tdat.input[2] = x3;
        tdat.input[3] = x1*x1;
        tdat.input[4] = x2*x2;
        tdat.input[5] = x3*x3;
        tdat.input[6] = x1*x2;
        tdat.input[7] = x2*x3;
        tdat.input[8] = x3*x1;
        tdat.input[9] = x1*x2*x3;

        tdat.output[0] = res1;
        tdat.output[1] = res2;
            
        glann_network_train(&numrec, &tdat);
    }

    printf("Training finished, save model to %s...\r\n",model_path);
    glann_network_save(&numrec, model_path);
    sleep(3);
    printf("Load model...\r\n");
    glann_network_load(&numrec ,model_path);

    float total_error = 0.f;

    for(j = 0; j < 200; j++){
        int index = j+100;

        float x1 = 0.002 + 0.004f * (float)index;
        float x2 = 0.002 - 0.004f * (float)index;
        float x3 = 0.002 + 0.005f * (float)index;

        float res1,res2;

        fun(x1,x2,x3,&res1,&res2);

        tdat.input[0] = x1;
        tdat.input[1] = x2;
        tdat.input[2] = x3;
        tdat.input[3] = x1*x1;
        tdat.input[4] = x2*x2;
        tdat.input[5] = x3*x3;
        tdat.input[6] = x1*x2;
        tdat.input[7] = x2*x3;
        tdat.input[8] = x3*x1;
        tdat.input[9] = x1*x2*x3;

        glann_network_run(&numrec, &tdat);

        float error[2];

        error[0] = res1 - tdat.output[0];
        error[1] = res2 - tdat.output[1];

        printf("\r\nnetwork input is        : %7.3f %7.3f %7.3f\r\n",tdat.input[0],tdat.input[1],tdat.input[2]);
        printf("expect output is        : %7.3f %7.3f\r\n",res1,res2);
        printf("actual network output is: %7.3f %7.3f\r\n",tdat.output[0],tdat.output[1]);
        printf("the error is            : %7.3f %7.3f\r\n", error[0], error[1]);
        total_error+= error[0] * error[0] + error[1] * error[1];
    }

    printf("the total error is %f\r\n", sqrt(total_error));

    return 0;
}